package util;

import java.io.File;
import java.io.FileInputStream;
import java.io.FileNotFoundException;
import java.io.IOException;
import java.io.InputStream;
import java.util.ArrayList;
import java.util.List;

import javax.xml.parsers.DocumentBuilder;
import javax.xml.parsers.DocumentBuilderFactory;
import javax.xml.parsers.ParserConfigurationException;

import org.w3c.dom.Document;
import org.w3c.dom.Element;
import org.w3c.dom.Node;
import org.w3c.dom.NodeList;
import org.xml.sax.SAXException;

public class Configuration {
	private List<ClassInformation> classInformations;
	private String componentScanPackage;
	private boolean isAnnotation;
	private String placeHolder;
	private List<Tag> tags;

	public Configuration() {
		classInformations = new ArrayList<ClassInformation>();
		tags = new ArrayList<Tag>();
	}

	public List<ClassInformation> getClassInformations() {
		return classInformations;
	}

	public void setClassInformations(List<ClassInformation> classInformations) {
		this.classInformations = classInformations;
	}

	public void addClassInformation(ClassInformation classInformation) {
		this.classInformations.add(classInformation);
	}

	public String getComponentScanPackage() {
		return componentScanPackage;
	}

	public void setComponentScanPackage(String componentScanPackage) {
		this.componentScanPackage = componentScanPackage;
	}

	public boolean isAnnotation() {
		return isAnnotation;
	}

	public void setAnnotation(boolean isAnnotation) {
		this.isAnnotation = isAnnotation;
	}

	public List<Tag> getTags() {
		return tags;
	}

	public void setTags(List<Tag> tags) {
		this.tags = tags;
	}

	public String getPlaceHolder() {
		return placeHolder;
	}

	public void setPlaceHolder(String placeHolder) {
		this.placeHolder = placeHolder;
	}

	public void loadRealConfigFile(String fileLocation)
			throws ParserConfigurationException, SAXException, IOException {
		File inputFile = new File(fileLocation);
		if (!inputFile.exists())
			return;

		InputStream inputXMLFile = null;

		try {
			inputXMLFile = new FileInputStream(inputFile);
		} catch (FileNotFoundException e) {
			e.printStackTrace();
		}

		if (inputXMLFile != null) {
			DocumentBuilderFactory factory = DocumentBuilderFactory
					.newInstance();
			DocumentBuilder docBuilder;
			try {
				docBuilder = factory.newDocumentBuilder();
				Document inputDoc = docBuilder.parse(inputXMLFile);

				inputDoc.getDocumentElement().normalize();
				Node beanRoot = inputDoc.getElementsByTagName("beans:beans")
						.item(0);

				NodeList configurationNodes = beanRoot.getChildNodes();
				for (int i = 0; i < configurationNodes.getLength(); ++i) {
					Node n = configurationNodes.item(i);
					if (n.getNodeType() == Node.ELEMENT_NODE) {
						Element configNode = (Element) n;

						if ("annotation-driven".equals(configNode.getTagName()))
							isAnnotation = true;
						else if ("context:component-scan".equals(configNode
								.getTagName())) {
							componentScanPackage = configNode
									.getAttribute("base-package");
						} else if ("context:property-placeholder"
								.equals(configNode.getTagName())) {
							placeHolder = configNode.getAttribute("location");
						} else {
							if ("beans:bean".equals(configNode.getTagName())) {
								ClassInformation classInformation = new ClassInformation();
								String id = configNode.getAttribute("id");
								String className = configNode
										.getAttribute("class");

								classInformation.setId(id);
								classInformation.setClassName(className);

								NodeList childTags = configNode.getChildNodes();
								for (int j = 0; j < childTags.getLength(); ++j) {
									n = childTags.item(j);
									if (n.getNodeType() == Node.ELEMENT_NODE) {
										Element childTag = (Element) n;
										classInformation.addChildTag(Tag
												.makeTag(childTag));
									}
								}

								classInformations.add(classInformation);
							} else {
								tags.add(Tag.makeTag(configNode));
							}

						}
					}
				}
			} catch (ParserConfigurationException e) {
				e.printStackTrace();
				throw e;
			} catch (SAXException e) {
				e.printStackTrace();
				throw e;
			} catch (IOException e) {
				e.printStackTrace();
				throw e;
			}
		}
	}

	public ClassInformation checkWithIDOfBean(String id) {
		ClassInformation newClassInformation = new ClassInformation();
		newClassInformation.setId(id);
		boolean isExist = false;

		for (ClassInformation classInformation : classInformations) {
			if (classInformation.getId().equals(id)) {
				newClassInformation = classInformation;
				isExist = true;
				break;
			}
		}
		if (!isExist)
			classInformations.add(newClassInformation);

		return newClassInformation;
	}

	public ClassInformation checkWithClassOfBean(String className) {
		ClassInformation newClassInformation = new ClassInformation();
		newClassInformation.setClassName(className);
		boolean isExist = false;

		for (ClassInformation classInformation : classInformations) {
			if (classInformation.getClassName().equals(className)) {
				newClassInformation = classInformation;
				isExist = true;
				break;
			}
		}
		if (!isExist)
			classInformations.add(newClassInformation);

		return newClassInformation;
	}
}